package visualOne;

import globalCode.TableHandler;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.swing.JPanel;

public class WheelPanel extends JPanel implements MouseWheelListener, KeyListener, MouseListener, MouseMotionListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private double size;
	private int num;
	private Connection con;
	private TableHandler th;
	private SortedMap<Integer, UserNode> nodeMap = new TreeMap<Integer, UserNode>();
	int groupID = 0;
	int[] userList = new int[0];
	int[][] userConList = new int[0][];
	double thetaMod = 0;
	int diameter = 2000;
	private boolean keyLeft = false, keyRight = false;
	boolean limitLines = false;
	int limitID = 0;
	private int maxConnectivity = 1;


	public WheelPanel(){
		this.setPreferredSize(new Dimension(diameter, diameter));
		this.setBackground(Color.BLACK);
		this.setDoubleBuffered(true);
		this.addMouseWheelListener(this);
		this.addKeyListener(this);
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		
		try {
			Class.forName("com.mysql.jdbc.Driver");
		} catch (ClassNotFoundException e) {
			return;
		}
		//System.setProperty("socksProxyHost", "e165tmg1");
		//System.setProperty("socksProxyPort", "80");
		
		//String url = "jdbc:mysql://pld-ischool02.fayette.ketsds.net";
		//String url = "jdbc:mysql://ischooldev.fcps.net";
		String url = "jdbc:mysql://dosshome.dyndns-office.com:63306";
		//String url = "jdbc:mysql://192.168.1.33:3306";
		//String url = "jdbc:mysql://localhost";
		String username = "root";
		String password = "PAss33word!!";

		try {
			con = DriverManager.getConnection(url, username, password);
		} catch (SQLException e) {
			e.printStackTrace();
			return;
		}

		th = new TableHandler(con);

	}

	public void setDiameter(int d){
		this.clear();
		diameter = d;
		if(diameter<1)
			diameter=1;
		this.setPreferredSize(new Dimension(diameter, diameter));
		this.recalc();
		this.repaint();
	}

	public void paint(Graphics g){
		this.inputLogic();

		this.requestFocus();

		Graphics2D g2D = (Graphics2D) g;
		g2D.setColor(Color.BLACK);
		g2D.fillRect(0, 0, diameter, diameter);
		g2D.setColor(Color.WHITE);
		for(int i = 0; i<userConList.length; i++){
			if(limitLines==false || userConList[i][0]==limitID || userConList[i][1]==limitID)
				if(nodeMap.get(userConList[i][0]) != null && nodeMap.get(userConList[i][1]) != null ){
					int x1 = (int)nodeMap.get(userConList[i][0]).x;
					int y1 = (int)nodeMap.get(userConList[i][0]).y;
					int x2 = (int)nodeMap.get(userConList[i][1]).x;
					int y2 = (int)nodeMap.get(userConList[i][1]).y;
					if(userConList[i][2]>1){
						g2D.setStroke(new BasicStroke(userConList[i][2]));
						g2D.drawLine(x1, y1, x2, y2);
					}
				}
		}
		//System.out.println("END OF LIST \n");

		for(Integer i: nodeMap.keySet()){
			nodeMap.get(i).draw(g);
		}
	}

	private void inputLogic() {
		double old = this.thetaMod;
		if(keyLeft)
			thetaMod-=2;
		if(keyRight)
			thetaMod+=2;

		if(thetaMod>=360)
			thetaMod-=360;
		if(thetaMod<0)
			thetaMod+=360;

		if(thetaMod!=old)
			recalc();
	}

	public void calcNum(int n){
		//Graphics g = this.getGraphics();
		double cirRad = diameter/2;
		num = n;
		double sz = 0;
		if(num==1)
			sz=cirRad;
		else if(num>=2)
			sz=cirRad*Math.sin(Math.PI/num)/3;

		size = sz;

		Point[] points = new Point[(int) num];
		double altCirRad = cirRad-size;
		if(num!=0)
			points[0] = new Point(275, (int)(size));
		for(int i = 1; i<num; i++){
			double theta = 2*(i)*Math.PI/num;
			int newX = (int) (275-altCirRad*Math.sin(theta));
			int newY = (int) (275-altCirRad*Math.cos(theta));
			points[i] = new Point(newX, newY);
		}

		System.out.println("Size: "+size);
		System.out.println("Points: ");
		for(int i = 0; i<num; i++)
			nodeMap.put(i, new UserNode(i, points[i].x, points[i].y, (int)size));	
	}

	public void calcGroup(int gID){
		groupID = gID;
		userList = th.usersInGroup(groupID);
		userConList = th.getShortArray(groupID);
		num = userList.length;
		int maxContiv = 1;
		for(int i = 0; i<num; i++){
			nodeMap.put(userList[i], new UserNode(userList[i], 0, 0, 0));
			int contiv = userConnectivity(userList[i]);
			if(contiv>maxContiv)
				maxContiv=contiv;
			nodeMap.get(userList[i]).setConnectivity(contiv);
		}
		maxConnectivity  = maxContiv;
		recalc();
	}
	
	public int userConnectivity(int uID){
		int value = 0;
		for(int i = 0; i<userConList.length; i++){
			if(userConList[i][0]==uID || userConList[i][1]==uID)
				value+=userConList[i][2];
		}
		return value;
	}

	public void recalc(){
		double cirRad = diameter/2;
		
		double sz = 0;
		if(num==1)
			sz=cirRad;
		else if(num>=2)
			sz=cirRad*Math.sin(Math.PI/num)/3;

		size = sz;
		
		Point[] points = new Point[(int) num];
		double altCirRad = cirRad-size;
		for(int i = 0; i<num; i++){
			System.out.println(nodeMap.get(userList[i]));
			double thisAltCirRad = (double)(maxConnectivity-nodeMap.get(userList[i]).getConnectivity())/maxConnectivity*altCirRad;
			double theta = 2*(i)*Math.PI/num+thetaMod*2*Math.PI/360.0;
			int newX = (int) (diameter/2-thisAltCirRad*Math.sin(theta));
			int newY = (int) (diameter/2-thisAltCirRad*Math.cos(theta));
			points[i] = new Point(newX, newY);
		}
		for(int i = 0; i<num; i++){
			UserNode user = nodeMap.get(userList[i]);
			user.x = points[i].x;
			user.y = points[i].y; 
			user.rad = (int)size;
		}
		
		boolean resetMoving = true;
		while(resetMoving){
			resetMoving=false;
			for(int i = 0; i<num; i++){
				UserNode user1 = nodeMap.get(userList[i]);
				for(int j = i+1; j<num; j++){
					UserNode user2 = nodeMap.get(userList[j]);
					if(user1.seperate(user2)){
						resetMoving=true;
						//System.out.println("repeat resetMoving="+i+" "+j);
						break;
					}
				}
				if(resetMoving)
					break;
				
			}
			
		}
		
		revalidate();
	}

	public void clear() {
		this.getParent().getParent().repaint();
		this.getGraphics().clearRect(0, 0, diameter*2, diameter*2);
	}

	@Override
	public void mouseWheelMoved(MouseWheelEvent arg0) {
		int rot = arg0.getWheelRotation();

		if(rot<0)
			setDiameter((int)((diameter+1)*1.25));
		else
			setDiameter((int)((diameter-1)/1.25));
		System.out.println(diameter+" dia");
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		switch (arg0.getKeyCode()){
		case KeyEvent.VK_LEFT:
			keyLeft = true;
			break;
		case KeyEvent.VK_RIGHT:
			keyRight = true;
			break;
		default:
			break;
		}
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		switch (arg0.getKeyCode()){
		case KeyEvent.VK_LEFT:
			keyLeft = false;
			break;
		case KeyEvent.VK_RIGHT:
			keyRight = false;
			break;
		default:
			break;
		}
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		

	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		//limitLines = false;
	}

	@Override
	public void mouseDragged(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseMoved(MouseEvent arg0) {
		for(Integer i: nodeMap.keySet()){
			UserNode u = nodeMap.get(i);

			if(u.contains(arg0.getX(), arg0.getY())){
				limitLines=true;
				limitID=u.id;
				return;
			}
		}
		limitLines=false;
	}


}
